/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package mathma.discrete.set;

import mathma.core.value.Complex;
import mathma.core.real.Real;
import mathma.core.value.Value;
import mathma.core.value.ValueType;

import mathma.discrete.pair.OrderedPair;

/**
 * @since 0.2.2
 * @author Ethan Levine
 */
public abstract class Set<E extends Value> extends Value<Set<E>> {

    private final Type setType;

    public final static ValueType GenericType =
            new ValueType(new SetSimplifier(), Set.class);

    public final static Set<Real> R = null; // TODO real numbers
    public final static Set<Real> N = null; // TODO natural numbers
    public final static Set<Real> Z = null; // TODO integers
    public final static Set<Complex> C = null; // TODO complex numbers

    protected Set(Type setType) {
        super(new ValueType<Set<E>>(new SetSimplifier<E>(), Set.class));
        this.setType = setType;
    }

    public Type getSetType() {
        return setType;
    }

    abstract public boolean isInfinite();

    abstract public boolean isCountable();

    abstract public boolean contains(E member);

    abstract public boolean isEqual(Set<E> other);

    abstract public boolean isDisjoint(Set<E> other);

    abstract public boolean isSubsetOf(Set<E> other);

    abstract public boolean isProperSubsetOf(Set<E> other);

    abstract public Set<E> union(Set<E> other);

    abstract public Set<E> intersect(Set<E> other);

    abstract public Set<E> compliment(Set<E> universal);

    abstract public Set<E> difference(Set<E> other);

    public Set<E> symmetricDifference(Set<E> other) {
        return difference(other).union(other.difference(this));
    }

    abstract public Set<OrderedPair<E>> crossProduct(Set<E> other);

    public enum Type {
        STATIC, DYNAMIC, CONDITIONAL
    }
}
